package com.cw.jeeyt.controller.process;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLStreamException;

import org.apache.commons.fileupload.FileItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.cw.jeeyt.api.dto.response.JsonResultDto;
import com.cw.jeeyt.common.DataTable;
import com.cw.jeeyt.common.ResultData;
import com.cw.jeeyt.common.StringUtils;
import com.cw.jeeyt.common.utils.UploadUtils4;
import com.cw.jeeyt.common.web.BaseController;
import com.cw.jeeyt.service.bo.process.RuExecution;
import com.cw.jeeyt.service.directive.PageDictDirective;
import com.cw.jeeyt.service.directive.PermissionDirective;
import com.cw.jeeyt.service.impl.process.ReProcDefService;
import com.cw.lang.common.config.Global;
import com.cw.lang.mybatis.dto.PageInfo;

import static com.cw.jeeyt.common.web.Servlets.renderResult;

/**
 * 流程定义相关Controller
 *
 * @author liuruijun
 * @version 2018-08-02
 */
@Controller
@RequestMapping(value = "/act/process")
public class ReProcDefController extends BaseController {

    @Autowired
    private ReProcDefService actProcessService;

    /**
     * 流程定义(流程管理)列表
     */
    @RequestMapping(value = {"list", ""})
    public String processList(Model model) {
        model.addAttribute("PageDict", new PageDictDirective());
        model.addAttribute("permission", new PermissionDirective());
        return "process/processList";
    }

    @ResponseBody
    @RequestMapping(value = {"listData"})
    public ResultData listData(@RequestBody DataTable dataTable, String category) {
        return actProcessService.processList(dataTable, category);
    }

    /**
     * 读取资源，通过部署ID
     *
     * @param procDefId 流程定义ID
     * @param proInsId 流程实例ID
     * @param resType 资源类型(xml|image)
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "resource/read")
    public void resourceRead(String procDefId, String proInsId, String resType, HttpServletResponse response)
    throws Exception {
        InputStream resourceAsStream = actProcessService.resourceRead(procDefId, proInsId, resType);
        byte[] temp = new byte[1024];
        if (resType.equals("image")) {
            response.setContentType("image/png");
        } else if (resType.equals("xml")) {
            response.setCharacterEncoding("utf-8");
            response.setContentType("text/xml; charset=utf-8");
        }
        int len = -1;
        while ((len = resourceAsStream.read(temp, 0, 1024)) != -1) {
            response.getOutputStream()
                .write(temp, 0, len);
        }
    }

    /**
     * 删除部署的流程，级联删除流程实例
     *
     * @param deploymentId 流程部署ID
     */
    @RequestMapping(value = "deleteDeployment")
    @ResponseBody
    public JsonResultDto deleteDeployment(String deploymentId, HttpServletResponse response) {

        JsonResultDto jsonResultDto = new JsonResultDto(false);
        try {
            actProcessService.deleteDeployment(deploymentId);
            jsonResultDto.setSuccess(true);
        } catch (Exception e) {
            e.printStackTrace();
            jsonResultDto.setMsg("删除失败：" + e.getMessage());
            logger.error("删除流程定义失败：" + e.getMessage());
        }
        return jsonResultDto;
    }

    /**
     * 挂起、激活流程实例
     */
    @RequestMapping(value = "update/{state}")
    @ResponseBody
    public JsonResultDto updateState(@PathVariable("state") String state, String procDefId, HttpServletResponse response) {
        JsonResultDto jsonResultDto = new JsonResultDto(false);
        try {
            actProcessService.updateState(state, procDefId);
            jsonResultDto.setSuccess(true);
        } catch (Exception e) {
            e.printStackTrace();
            jsonResultDto.setMsg("挂起、激活失败：" + e.getMessage());
            logger.error("挂起、激活失败：" + e.getMessage());
        }
        return jsonResultDto;
    }

    @RequestMapping(value = "/deploy", method = RequestMethod.GET)
    public String deploy(Model model) {
        model.addAttribute("permission", new PermissionDirective());
        model.addAttribute("PageDict", new PageDictDirective());
        return "process/processDeploy_form";
    }

    /**
     * 部署流程 - 保存
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "/deploy", method = RequestMethod.POST)
    @ResponseBody
    public JsonResultDto deploy(HttpServletRequest request) {
        String msg;
        JsonResultDto jsonResultDto = new JsonResultDto(false);
        try {
            Map<String, Object> fieldsMap = UploadUtils4.getInstance()
                .initFields(request);
            FileItem fileItem = ((List<FileItem>) fieldsMap.get(UploadUtils4.FILE_FIELDS)).get(0);
            String category = ((Map<String, String>) fieldsMap.get(UploadUtils4.FORM_FIELDS)).get("category");

            if (fileItem == null || StringUtils.isBlank(fileItem.getName())) {
                msg = "请选择要部署的流程文件";
            } else {
                msg = actProcessService.deploy(category, fileItem);
            }
            jsonResultDto.setMsg(msg);
            jsonResultDto.setSuccess(true);
        } catch (Exception e) {
            e.printStackTrace();
            jsonResultDto.setMsg("部署失败：" + e.getMessage());
            logger.error("部署失败：" + e.getMessage());
        }
        return jsonResultDto;
    }

    @RequestMapping(value = "running")
    public String runningList() {
        return "modules/flow/flowProcessRunningList";
    }

    /**
     * 运行中的实例列表
     */
    @RequestMapping(value = "runningData")
    @ResponseBody
    public PageInfo<RuExecution> runningData(String procInsId, String procDefKey, HttpServletRequest request,
        HttpServletResponse response) {
        PageInfo<RuExecution> page = actProcessService.runningList(new PageInfo<>(), procInsId, procDefKey);
        return page;
    }

    /**
     * 删除流程实例
     *
     * @param procInsId 流程实例ID
     * @param reason 删除原因
     */
    @RequestMapping(value = "deleteProcIns")
    @ResponseBody
    public String deleteProcIns(String procInsId, String reason) {
        if (Global.isDemoMode()) {
            return renderResult(Global.FALSE, "演示模式，不允许操作！");
        }
        String msg;
        if (StringUtils.isBlank(reason)) {
            msg = "删除流程实例失败，请填写删除原因";
        } else {
            actProcessService.deleteProcIns(procInsId, reason);
            msg = "删除流程实例成功，实例ID=" + procInsId;
        }
        return renderResult(Global.TRUE, msg);
    }

    /**
     * 设置流程分类
     */
    @RequestMapping(value = "updateCategory")
    public String updateCategory(String procDefId, String category, RedirectAttributes redirectAttributes) {
        actProcessService.updateCategory(procDefId, category);
        return "redirect:/act/process";
    }

    /**
     * 将部署的流程转换为模型
     *
     * @param procDefId
     * @param redirectAttributes
     * @return
     * @throws UnsupportedEncodingException
     * @throws XMLStreamException
     */
    @RequestMapping(value = "convert/toModel")
    public String convertToModel(String procDefId, RedirectAttributes redirectAttributes)
    throws UnsupportedEncodingException, XMLStreamException {
        org.flowable.engine.repository.Model modelData = actProcessService.convertToModel(procDefId);
        redirectAttributes.addFlashAttribute("message", "转换模型成功，模型ID=" + modelData.getId());
        return "redirect:/act/model";
    }

    /**
     * 导出图片文件到硬盘
     */
    @RequestMapping(value = "export/diagrams")
    @ResponseBody
    public List<String> exportDiagrams(@Value("#{APP_PROP['activiti.export.diagram.path']}") String exportDir)
    throws IOException {
        List<String> files = actProcessService.exportDiagrams(exportDir);
        ;
        return files;
    }

}
